#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

int speed_arr[] = {B0, B50, B75, B110, B134, B150, B200,
									 B300, B600, B1200, B1800, B2400, B4800,
									 B9600, B19200, B38400, B57600, B115200,
									 B230400, B460800, };

int name_arr[] = {0, 50, 75, 110, 134, 150, 200,
									300, 600, 1200, 1800, 2400, 4800,
									9600, 19200, 38400, 57600, 115200,
									230400, 460800, };

void set_speed(int fd, int speed)
{
	int status;
	struct termios opt;

	tcgetattr(fd, &opt);

	for(int i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
	{
		if(speed == name_arr[i]){
			tcflush(fd, TCIOFLUSH);

			cfsetispeed(&opt, speed_arr[i]);
			cfsetospeed(&opt, speed_arr[i]);
			status = tcsetattr(fd, TCSANOW, &opt);
			if (status != 0) 
			{
				perror("tcsetattr fd");
				return;
			}

			tcflush(fd,TCIOFLUSH);
		}
	}
}

int set_parity(int fd, int databits, int stopbits, int parity)
{
	struct termios options;

	if(tcgetattr(fd, &options) != 0)
	{
		perror("Setup Serial Error!");
		return -1;
	}

	options.c_cflag &= ~CSIZE;
	
	switch(databits)
	{
		case 7:
			options.c_cflag |= CS7;
			break;
		case 8:
			options.c_cflag |= CS8;
			break;
		default:
			fprintf(stderr, "Unsupported data size\n");
			return -1;
	}

	switch(parity)
	{
		case 'n':
		case 'N':
			options.c_cflag &= ~PARENB;
			options.c_iflag &= ~INPCK;
			break;
		case 'o':
		case 'O':
			options.c_cflag |= (PARODD | PARENB);
			options.c_iflag |= INPCK;
			break;
		case 'e':
		case 'E':
			options.c_cflag |= PARENB;
			options.c_cflag &= ~PARODD;
			options.c_iflag |= INPCK;
			break;
		 case 'S': 
     case 's': /*as no parity*/ 
	     options.c_cflag &= ~PARENB; 
	     options.c_cflag &= ~CSTOPB; 
	     break; 
     default: 
	     fprintf(stderr,"Unsupported parity\n"); 
	     return -1; 
	}

	switch (stopbits) 
	{ 
		case 1: 
			options.c_cflag &= ~CSTOPB; 
			break; 
		case 2: 
			options.c_cflag |= CSTOPB; 
			break; 
		default: 
			fprintf(stderr,"Unsupported stop bits\n"); 
			return -1; 
	}

	if (parity != 'n') 
	{
		options.c_iflag |= INPCK; 
	}

	tcflush(fd, TCIFLUSH); 
	options.c_cc[VTIME] = 150; 
	options.c_cc[VMIN] = 0; 

	if (tcsetattr(fd, TCSANOW, &options) != 0) 
	{ 
			perror("Setup Serial Error"); 
			return -1; 
	} 
	return 0; 
}

int OpenDev(char *Dev) 
{
	int fd = open(Dev, O_RDWR ); //| O_NOCTTY | O_NDELAY  
	if (-1 == fd) 
	{ 
		perror("Can't Open Serial Port"); 
		return -1; 
	} 
	else 
	{
		return fd; 
	}
}

int main(int argc, char **argv) 
{
	int fd; 
	int nread; 
	char buff[512];
	char *dev = "/dev/ttyS1"; 
	fd = OpenDev(dev); 
	set_speed(fd, 19200); 
	if (set_parity(fd, 8, 1, 'N') == -1) 
	{ 
		printf("Set Parity Error\n"); 
		exit (0); 
	} 
	while (1) 
	{ 
		while ((nread = read(fd, buff, 512))>0) 
		{ 
			printf("\nLen %d\n", nread); 								           
			buff[nread+1] = '\0'; 				
			printf("\n%s", buff); 
		} 
	}
}
